package com.taldh.design.patterns.singleton;

/**
 * double checking 问题是因为多线程访问的时候队列阻塞引起的问题的解决方案。
 *
 * date: 2020/5/24
 *
 * @author 袁小黑
 * @version 1.0.0
 */

public class LazyLoadedDoubldCheckingInvoryTower {

    private volatile LazyLoadedDoubldCheckingInvoryTower invoryTower = null;

    private LazyLoadedDoubldCheckingInvoryTower() {
    }

    public LazyLoadedDoubldCheckingInvoryTower getInstance() {
//        if (invoryTower == null) {
//            synchronized (LazyLoadedDoubldCheckingInvoryTower.class) {
//                if (invoryTower == null) {
//                    invoryTower = new LazyLoadedDoubldCheckingInvoryTower();
//                }
//            }
//        }
//
//        return invoryTower;

        //上面是我写的，都是invoryTower没使用临时变量，性能没得到最大的提升， 更好的例子如下：
        // local variable increases performance by 25 percent
        // Joshua Bloch "Effective Java, Second Edition", p. 283-284
        LazyLoadedDoubldCheckingInvoryTower result = invoryTower;
        // Check if singleton instance is initialized.
        // If it is initialized then we can return the instance.
        if (result == null) {
            // It is not initialized but we cannot be sure because some other thread might have
            // initialized it in the meanwhile.
            // So to make sure we need to lock on an object to get mutual exclusion.
            synchronized (LazyLoadedDoubldCheckingInvoryTower.class) {
                // Again assign the instance to local variable to check if it was initialized by some
                // other thread while current thread was blocked to enter the locked zone.
                // If it was initialized then we can return the previously created instance
                // just like the previous null check.
                result = invoryTower;
                if (result == null) {
                    // The instance is still not initialized so we can safely
                    // (no other thread can enter this zone)
                    // create an instance and make it our singleton instance.
                    invoryTower = result = new LazyLoadedDoubldCheckingInvoryTower();
                }
            }
        }
        return result;
    }

}
